package com.tiancheng.trade.order.configuration;


import com.tiancheng.trade.order.util.CommonUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 将请求参数带有下划线转驼峰命名
 */
@Slf4j
@Component
public class UnderlineToCamelArgumentResolver implements HandlerMethodArgumentResolver {

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        String method = methodParameter.getMethod().getName();
        Class<?> ptype = methodParameter.getParameterType();
        Boolean isPrimitive = CharSequence.class.isAssignableFrom(ptype) || Number.class.isAssignableFrom(ptype);

        boolean isForm = methodParameter.hasParameterAnnotation(RequestForm.class);

        return !isPrimitive && (isForm ||
                StringUtils.startsWith(method, "find") || StringUtils.startsWith(method, "query") || StringUtils.startsWith(method, "get"));
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        return handleParameterNames(parameter, webRequest);
    }

    private Object handleParameterNames(MethodParameter parameter, NativeWebRequest webRequest) throws JsonProcessingException {

        Class clz = parameter.getParameterType();
        Field[] fields = clz.getDeclaredFields();
        List<String> fieldNames = Stream.of(fields).map(Field::getName).collect(Collectors.toList());

        Map<String, Object> param = new HashMap<>();
        Iterator<String> paramNames = webRequest.getParameterNames();
        while (paramNames.hasNext()) {
            String paramName = paramNames.next();
            try {
                String value = webRequest.getParameter(paramName);
                String humpName = CommonUtil.underlineToHump(paramName);

                Object transValue = value;
                if(fieldNames.contains(humpName)) {
                    Field field = clz.getDeclaredField(humpName);
                    if(field.getType().isArray()) {
                        transValue = value.split(",");
                    }
                }
                param.put(paramName, transValue);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        String json = objectMapper.writeValueAsString(param);
        return objectMapper.readValue(json, parameter.getParameterType());
    }

}
